//! tracing Layer 实现
//!
//! 提供 log4r 与 tracing 生态的集成。
//!
//! ## 主要类型
//!
//! - [`Log4rLayer`] - tracing Layer 实现，处理日志事件
//!
//! ## 示例
//!
//! ```rust,ignore
//! use log4r::layer::Log4rLayer;
//! use tracing_subscriber::prelude::*;
//!
//! let layer = Log4rLayer::new(sender, Level::Info);
//! let subscriber = tracing_subscriber::registry().with(layer);
//! tracing::subscriber::set_global_default(subscriber).ok();
//! ```

use std::borrow::Cow;

use crossbeam_channel::Sender;
use tracing::field::{Field, Visit};
use tracing::{Event, Subscriber};
use tracing_subscriber::layer::Context;
use tracing_subscriber::Layer;

use crate::event::LogEvent;
use crate::level::Level;

/// log4r 的 tracing Layer 实现
///
/// 将 tracing 事件转换为 log4r 的 LogEvent 并发送到异步通道。
///
/// ## 线程安全
///
/// `Log4rLayer` 实现了 `Send + Sync`，可以安全地在多线程环境中使用。
pub struct Log4rLayer {
    /// 日志通道发送端
    sender: Sender<LogEvent>,
    /// 全局级别过滤
    level_filter: Level,
}

// 编译时断言：验证 Log4rLayer 实现 Send + Sync
const _: () = {
    const fn assert_send_sync<T: Send + Sync>() {}
    assert_send_sync::<Log4rLayer>();
};

impl Log4rLayer {
    /// 创建新的 Log4rLayer
    ///
    /// # Arguments
    ///
    /// * `sender` - 日志通道发送端
    /// * `level_filter` - 全局级别过滤阈值
    pub fn new(sender: Sender<LogEvent>, level_filter: Level) -> Self {
        Self {
            sender,
            level_filter,
        }
    }

    /// 检查是否应该记录该日志
    fn should_log(&self, level: Level) -> bool {
        level >= self.level_filter
    }
}

/// tracing Level 到 log4r Level 的转换
fn convert_tracing_level(level: &tracing::Level) -> Level {
    match *level {
        tracing::Level::TRACE => Level::Trace,
        tracing::Level::DEBUG => Level::Debug,
        tracing::Level::INFO => Level::Info,
        tracing::Level::WARN => Level::Warn,
        tracing::Level::ERROR => Level::Error,
    }
}

/// 用于提取事件消息的 Visitor
struct MessageVisitor {
    message: String,
    is_fatal: bool,
}

impl MessageVisitor {
    fn new() -> Self {
        Self {
            message: String::new(),
            is_fatal: false,
        }
    }
}

impl Visit for MessageVisitor {
    fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) {
        if field.name() == "message" {
            self.message = format!("{:?}", value);
            // 移除首尾的引号（如果存在）
            if self.message.starts_with('"') && self.message.ends_with('"') {
                self.message = self.message[1..self.message.len() - 1].to_string();
            }
        }
    }

    fn record_str(&mut self, field: &Field, value: &str) {
        if field.name() == "message" {
            self.message = value.to_string();
        }
    }

    fn record_bool(&mut self, field: &Field, value: bool) {
        if field.name() == "fatal" && value {
            self.is_fatal = true;
        }
    }
}

impl<S> Layer<S> for Log4rLayer
where
    S: Subscriber + for<'a> tracing_subscriber::registry::LookupSpan<'a>,
{
    fn on_event(&self, event: &Event<'_>, _ctx: Context<'_, S>) {
        let metadata = event.metadata();
        let level = convert_tracing_level(metadata.level());

        // 级别过滤
        if !self.should_log(level) {
            return;
        }

        // 提取消息
        let mut visitor = MessageVisitor::new();
        event.record(&mut visitor);

        // 如果没有 message 字段，尝试使用整个事件的格式化输出
        let message = if visitor.message.is_empty() {
            // 使用 tracing 的默认格式化
            let mut msg = String::new();
            let mut first = true;
            event.record(&mut FieldCollector {
                output: &mut msg,
                first: &mut first,
            });
            msg
        } else {
            visitor.message
        };

        // 确定最终级别（如果标记为 fatal，提升到 Fatal）
        let final_level = if visitor.is_fatal {
            Level::Fatal
        } else {
            level
        };

        // 构建 LogEvent
        let log_event = LogEvent {
            timestamp: time::OffsetDateTime::now_local()
                .unwrap_or_else(|_| time::OffsetDateTime::now_utc()),
            level: final_level,
            target: Cow::Owned(metadata.target().to_string()),
            message: Cow::Owned(message),
            write_to_syslog: final_level == Level::Fatal,
        };

        // 发送到通道（忽略发送失败，避免阻塞用户代码）
        let _ = self.sender.try_send(log_event);
    }

    fn enabled(&self, metadata: &tracing::Metadata<'_>, _ctx: Context<'_, S>) -> bool {
        let level = convert_tracing_level(metadata.level());
        self.should_log(level)
    }
}

/// 用于收集所有字段的 Visitor
struct FieldCollector<'a> {
    output: &'a mut String,
    first: &'a mut bool,
}

impl Visit for FieldCollector<'_> {
    fn record_debug(&mut self, field: &Field, value: &dyn std::fmt::Debug) {
        if !*self.first {
            self.output.push_str(", ");
        }
        *self.first = false;

        if field.name() == "message" {
            // message 字段直接输出值
            let formatted = format!("{:?}", value);
            // 移除首尾的引号
            if formatted.starts_with('"') && formatted.ends_with('"') {
                self.output.push_str(&formatted[1..formatted.len() - 1]);
            } else {
                self.output.push_str(&formatted);
            }
        } else {
            // 其他字段输出 key=value 格式
            self.output
                .push_str(&format!("{}={:?}", field.name(), value));
        }
    }

    fn record_str(&mut self, field: &Field, value: &str) {
        if !*self.first {
            self.output.push_str(", ");
        }
        *self.first = false;

        if field.name() == "message" {
            self.output.push_str(value);
        } else {
            self.output.push_str(&format!("{}={}", field.name(), value));
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crossbeam_channel::bounded;

    // UT-7.1-L01: 测试 Log4rLayer 创建
    #[test]
    fn test_log4r_layer_new() {
        // GIVEN: 一个 channel
        let (sender, _receiver) = bounded::<LogEvent>(100);

        // WHEN: 创建 Log4rLayer
        let layer = Log4rLayer::new(sender, Level::Info);

        // THEN: 应成功创建
        assert_eq!(layer.level_filter, Level::Info);
    }

    // UT-7.1-L02: 测试级别过滤
    #[test]
    fn test_should_log_level_filter() {
        // GIVEN: 配置 WARN 级别的 layer
        let (sender, _receiver) = bounded::<LogEvent>(100);
        let layer = Log4rLayer::new(sender, Level::Warn);

        // WHEN/THEN: 检查各级别
        assert!(!layer.should_log(Level::Trace));
        assert!(!layer.should_log(Level::Debug));
        assert!(!layer.should_log(Level::Info));
        assert!(layer.should_log(Level::Warn));
        assert!(layer.should_log(Level::Error));
        assert!(layer.should_log(Level::Fatal));
    }

    // UT-7.1-L03: 测试 tracing Level 转换
    #[test]
    fn test_convert_tracing_level() {
        assert_eq!(convert_tracing_level(&tracing::Level::TRACE), Level::Trace);
        assert_eq!(convert_tracing_level(&tracing::Level::DEBUG), Level::Debug);
        assert_eq!(convert_tracing_level(&tracing::Level::INFO), Level::Info);
        assert_eq!(convert_tracing_level(&tracing::Level::WARN), Level::Warn);
        assert_eq!(convert_tracing_level(&tracing::Level::ERROR), Level::Error);
    }

    // UT-7.1-L04: 测试 Log4rLayer 实现 Send + Sync
    #[test]
    fn test_log4r_layer_send_sync() {
        fn assert_send_sync<T: Send + Sync>() {}
        assert_send_sync::<Log4rLayer>();
    }

    // UT-7.1-L05: 测试 MessageVisitor
    #[test]
    fn test_message_visitor() {
        let visitor = MessageVisitor::new();
        assert!(visitor.message.is_empty());
        assert!(!visitor.is_fatal);
    }
}
